const app = require('express').Router()
const fs = require('fs');
const request = require('request')
const axios = require('axios');

// 处理队列
class RequestQueue {
  constructor(id) {
    this.arrayLength = global.myConfig.numberOfQueues
    this.queue = Array.from({
      length: this.arrayLength
    }, () => []);;
    this.isProcessing = false;
    this.total = 0
    this.usableTotal = 0
    this.id = id
    this.requestCount = 0
    this.currentPointer = 0
    this.clearArr = []
    this.viewTimes = 0
    this.startTime = new Date().getTime()
  }

  addRequest(url, options) {
    this.requestCount++
    this.queue[this.currentPointer].push({
      url,
      options
    })
    if (this.currentPointer == this.arrayLength - 1) {
      this.currentPointer = 0
    } else {
      this.currentPointer++
    }
    // this.queue.push({ url, options });

    // if (!this.isProcessing) {
    //   this.processQueue();
    // }
  }
  initiate() {
    for (let i = 0; i < this.arrayLength; i++) {
      this.processQueue(i);
    }
  }

  // 查看是否清空
  inspect() {
    if (this.clearArr.length == this.arrayLength) {
      let endTime = new Date().getTime()
      console.log('导出完毕，用时:' + (endTime - this.startTime) + 'ms')
      setTimeout(() => {
        global.pool.query(`UPDATE ${global.myConfig.pool.serviceTable} SET section = 1 WHERE id = '${this.id}'`, (err, result) => {
          if (err) {
            console.error('查询数据出错:', err);
            return;
          }
        });
        global.pool.query(`UPDATE ${global.myConfig.pool.serviceTable} SET scale = 100 WHERE id = '${this.id}'`, (err, result) => {
          if (err) {
            console.error('查询数据出错:', err);
            return;
          }
        });
      }, 1000)
      return;
    }
  }

  processQueue(num) {
    let scale = this.usableTotal / this.requestCount * 100
    global.pool.query(`UPDATE ${global.myConfig.pool.serviceTable} SET scale = ${scale} WHERE id = '${this.id}'`, (err, result) => {
      if (err) {
        console.error('查询数据出错:', err);
        return;
      }
    });
    if (this.queue[num].length === 0) {
      this.clearArr.push(num)
      this.inspect()
      return
    }

    const {
      url,
      options
    } = this.queue[num].shift();
    fs.stat(options.destPath, (err, stats) => {
      if (err) {
        // 发起网络请求
        let readStream = request(url).on('response', (response) => {
          if (response.statusCode == 200) {
            this.usableTotal++
            readStream.pipe(fs.createWriteStream(options.destPath))
          }
          this.processQueue(num); // 处理下一个请求
        })
      }
      if (stats) {
        this.usableTotal++
        this.processQueue(num);
        return
      }
    })
    // if (fs.existsSync(options.destPath)) {
    //   this.usableTotal++
    //   this.processQueue(num);
    //   return
    // }
  }
}
// 调用接口获取信息
let getLayerData = async (name) => {
  let res = await axios.get(`${global.myConfig.mapServerIp}/rasterserver/terrain/${name}/layer.json`)
  return res.data
}
// 地形创建第一层文件夹
let createFirst = (available, requestUrl, src, queue) => {
  for (let i = 0; i < available.length; i++) {
    let url = requestUrl + `/${i}`
    if (!fs.existsSync(`${src}/${i}`)) {
      fs.mkdirSync(`${src}/${i}`);
    }
    let isFirstEnd = false
    if (i == available.length - 1) {
      isFirstEnd = true
    }
    available[i].forEach(item => {
      createSecond(item, `${src}/${i}`, url, queue, isFirstEnd)
    })
  }
}
// 地形创建第二层文件夹
let createSecond = (second, path, requestUrl, queue, isEnd = false) => {
  for (let i = second.startX; i <= second.endX; i++) {
    let url = requestUrl + `/${i}`
    if (!fs.existsSync(`${path}/${i}`)) {
      fs.mkdirSync(`${path}/${i}`);
    }
    let isSecondEnd = false
    if (isEnd) {
      if (i == second.endX) {
        isSecondEnd = true
      }
    }
    setDataToSecond(second, `${path}/${i}`, url, queue, isSecondEnd)
  }
}
// 把地形数据下载到第二层文件夹中
let setDataToSecond = async (second, path, requestUrl, queue, isEnd = false) => {
  for (let i = second.startY; i <= second.endY; i++) {
    let url = requestUrl + `/${i}.terrain`
    let destPath = path + `/${i}.terrain`
    // 添加请求到队列中
    queue.addRequest(url, {
      destPath: destPath
    })
    if (isEnd) {
      if (i == second.endY) {
        queue.initiate()
      }
    }
  }
}
// 调用接口下载地形信息
app.post('/terrainExport', async (req, res) => {
  try {
    let {
      name,
      id,
      src
    } = req.body;
    // 处理src中的\
    let arr = src.split('\\')
    src = ''
    arr.forEach(item => {
      if (item) {
        src += item + '/'
      }
    })
    // 创建请求队列实例
    const queue = new RequestQueue(id);
    let data = await getLayerData(name)
    let path = `${global.myConfig.mapServerIp}/rasterserver/terrain/${encodeURIComponent(name)}/256`
    let fileSrc = `${src}256`
    if (!fs.existsSync(fileSrc)) {
      fs.mkdirSync(fileSrc);
    }
    fs.writeFileSync(`${src}/layer.json`, JSON.stringify(data))
    createFirst(data.available, path, fileSrc, queue)
    res.status(200).send({
      status: 200,
      msg: '导出任务创建成功'
    })
  } catch (error) {
    console.log(error)
    res.send(error)
  }
})

// 获取地图bbox
let getMapBbox = async (bbox, defaultLevel) => {
  // let defaultLevel = [8, 9, 10, 11, 12]
  // 西北坐标
  let northwest = [bbox[0], bbox[3]]
  // 西南坐标
  let southwest = [bbox[0], bbox[1]]
  // 东北坐标
  let northeast = [bbox[2], bbox[3]]
  // 东南坐标
  let southeast = [bbox[2], bbox[1]]
  let levelAndBbox = []
  for (let i = 0; i < defaultLevel.length; i++) {
    let ob = {
      level: defaultLevel[i],
      bbox: await getRequestByCoord(northwest, southwest, northeast, southeast, defaultLevel[i])
    }
    levelAndBbox.push(ob)
  }
  return levelAndBbox
}
// 根据坐标获取到请求
let getRequestByCoord = async (northwest, southwest, northeast, southeast, level) => {
  let northwestRequest = axios.get(`${global.myConfig.mapServerIp}/${global.myConfig.prefix}/services/getExtentByXY?lon=${northwest[0]}&lat=${northwest[1]}&level=${level}&tileSize=512&unit=degree`)
  let southwestRequest = axios.get(`${global.myConfig.mapServerIp}/${global.myConfig.prefix}/services/getExtentByXY?lon=${southwest[0]}&lat=${southwest[1]}&level=${level}&tileSize=512&unit=degree`)
  let northeastRequest = axios.get(`${global.myConfig.mapServerIp}/${global.myConfig.prefix}/services/getExtentByXY?lon=${northeast[0]}&lat=${northeast[1]}&level=${level}&tileSize=512&unit=degree`)
  let southeastRequest = axios.get(`${global.myConfig.mapServerIp}/${global.myConfig.prefix}/services/getExtentByXY?lon=${southeast[0]}&lat=${southeast[1]}&level=${level}&tileSize=512&unit=degree`)
  let res = null
  await Promise.all([northwestRequest, southwestRequest, northeastRequest, southeastRequest]).then(responses => {
    let arrX = []
    let arrY = []
    for (let i = 0; i < responses.length; i++) {
      let item = responses[i]
      arrX.push(item.data.data.x)
      arrY.push(item.data.data.y)
    }
    res = {
      startX: Math.min(...arrX),
      endX: Math.max(...arrX),
      startY: Math.min(...arrY),
      endY: Math.max(...arrY)
    }
  })
  return res
}
// 影像创建第一层文件夹
let createImageFirst = (available, requestUrl, src, queue) => {
  for (let i = 0; i < available.length; i++) {
    let url = requestUrl + `/${available[i].level}`
    if (!fs.existsSync(`${src}/${available[i].level}`)) {
      fs.mkdirSync(`${src}/${available[i].level}`);
    }
    let isFirstEnd = false
    if (i == available.length - 1) {
      isFirstEnd = true
    }
    createImageSecond(available[i].bbox, `${src}/${available[i].level}`, url, queue, isFirstEnd)
  }
}
// 影像创建第二层文件夹
let createImageSecond = (second, path, requestUrl, queue, isEnd = false) => {
  for (let i = second.startX; i <= second.endX; i++) {
    let url = requestUrl + `/${i}`
    if (!fs.existsSync(`${path}/${i}`)) {
      fs.mkdirSync(`${path}/${i}`);
    }
    let isSecondEnd = false
    if (isEnd) {
      if (i == second.endX) {
        isSecondEnd = true
      }
    }
    setDataToImageSecond(second, `${path}/${i}`, url, queue, isSecondEnd)
  }
}
// 把影像瓦片数据下载到第二层文件夹中
let setDataToImageSecond = async (second, path, requestUrl, queue, isEnd = false) => {
  for (let i = second.startY; i <= second.endY; i++) {
    let url = requestUrl + `/${i}/getMap?tilesize=512`
    let destPath = path + `/${i}.png`
    // 添加请求到队列中
    queue.addRequest(url, {
      destPath: destPath
    })
    if (isEnd) {
      if (i == second.endY) {
        queue.initiate()
      }
    }
  }
}

// 调用接口下载瓦片信息
app.post('/imageExport', async (req, res) => {
  try {
    let {
      name,
      id,
      src
    } = req.body;
    let arr = src.split('\\')
    src = ''
    arr.forEach(item => {
      if (item) {
        src += item + '/'
      }
    })
    // 创建请求队列实例
    const queue = new RequestQueue(id);
    let bbox = await axios.get(`${global.myConfig.mapServerIp}/rasterserver/image/getServiceBBox/${encodeURIComponent(name)}`)
    let serverInfo = await axios.get(`${global.myConfig.mapServerIp}/${global.myConfig.prefix}/dataservice/getInfo/${id}`)
    let styleInfo = JSON.parse(serverInfo.data.data.config).styleJson
    let defaultLevel = []
    Object.keys(styleInfo).forEach(item => {
      let levelRange = item.split('-')
      for (let i = parseInt(levelRange[0]); i <= parseInt(levelRange[1]); i++) {
        defaultLevel.push(i)
      }
    })
    let path = `${global.myConfig.mapServerIp}/rasterserver/image/${encodeURIComponent(name)}`
    let fileSrc = `${src}512`
    let bboxInfo = await getMapBbox(bbox.data, defaultLevel)
    if (!fs.existsSync(fileSrc)) {
      fs.mkdirSync(fileSrc);
    }
    createImageFirst(bboxInfo, path, fileSrc, queue)
    res.status(200).send({
      status: 200,
      msg: '导出任务创建成功'
    })
  } catch (error) {
    console.log(error)
    res.send(error)
  }
})

module.exports = app;